package com.cl.blog.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cl.blog.document.ContentDoc;
import com.cl.blog.entity.BContent;
import com.cl.blog.entity.BType;
import com.cl.blog.entity.BUser;
import com.cl.blog.service.BContentService;
import com.cl.blog.service.BTypeService;
import com.cl.blog.service.BUserService;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.core.TimeValue;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Author 付
 * @Date 2024-05-09 15:01
 * @Version 1.0
 * @description 搜索引擎业务处理
 * @since 1.0
 */
@Service
public class ESService {

	@Autowired
	RestHighLevelClient restHighLevelClient;

	@Autowired
	BContentService bContentService;
	@Autowired
	BUserService bUserService;
	@Autowired
	BTypeService bTypeService;

	/**
	 * 数据同步
	 *
	 * @return true-成功，false-失败
	 */
	public boolean dataSynchronization() throws IOException {
		List<BContent> list = bContentService.list(new QueryWrapper<BContent>()
				.eq("status", 2)
				.eq("is_delete", 0)
		);
		if (list.size() <= 0) {
			return false;
		}
		List<ContentDoc> docs = new ArrayList<>();
		for (BContent bContent : list) {

			BUser bUser = bUserService.getById(bContent.getUserId());
			if (bUser != null) {
				bContent.setAuthor(bUser.getNickname());
			}
			BType bType = bTypeService.getById(bContent.getTypeId());
			if (bType != null) {
				bContent.setTypeName(bType.getName());
			}
			ContentDoc contentDoc = new ContentDoc();
			contentDoc.setId(bContent.getId());
			contentDoc.setAuthor(bContent.getAuthor());
			contentDoc.setTitle(bContent.getTitle());
			contentDoc.setTypeName(bContent.getTypeName());
			docs.add(contentDoc);
		}

		BulkRequest bulkRequest = new BulkRequest();

		for (int i = 0; i < docs.size(); i++) {
			bulkRequest.add(new IndexRequest("blog_index")
					.id("" + (i + 1))
					.timeout(new TimeValue(20000, TimeUnit.SECONDS))
					.source(JSON.toJSONString(docs.get(i)), XContentType.JSON)
			);
		}
		BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
		return !bulk.hasFailures();
	}

	public List<Map<String, Object>> search(String keyword) throws IOException {
		SearchRequest searchRequest = new SearchRequest("blog_index");
		SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
		MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders
				.multiMatchQuery(keyword, "title", "author", "typeName")
				.type(MultiMatchQueryBuilder.Type.BEST_FIELDS);

		HighlightBuilder highlightBuilder = new HighlightBuilder();
		highlightBuilder.preTags("<span style='color:red'>");
		highlightBuilder.postTags("</span>");
		// 关闭多个高亮，也就是出现多个关键词时，只显示一个高亮
		highlightBuilder.requireFieldMatch(false);
		highlightBuilder.field("author").field("title").field("typeName");
		searchSourceBuilder.highlighter(highlightBuilder);

		searchSourceBuilder.query(multiMatchQueryBuilder);
		searchRequest.source(searchSourceBuilder);
		SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
		List<Map<String, Object>> list = new ArrayList<>();
		for (SearchHit hit : search.getHits().getHits()) {
			System.out.println("数据--"+hit);
			// 对于高亮的字段需要处理
			// 获取高亮字段
			Map<String, HighlightField> highlightFields = hit.getHighlightFields();
			HighlightField title = highlightFields.get("title");
			HighlightField author = highlightFields.get("author");
			HighlightField typeName = highlightFields.get("typeName");
			System.out.println("高亮字段--title--"+title);
			System.out.println("高亮字段--author--"+author);
			System.out.println("高亮字段--typeName--"+typeName);
			// 原来的数据
			Map<String, Object> sourceAsMap = hit.getSourceAsMap();
			if (title != null) {
				Text[] fragments = title.fragments();
				String new_name = "";
				for (Text text : fragments) {
					new_name += text;
				}
				// 将高亮字段替换原来的字段
				sourceAsMap.put("title", new_name);
			}
			if (author != null) {
				Text[] fragments = author.fragments();
				String new_name = "";
				for (Text text : fragments) {
					new_name += text;
				}
				// 将高亮字段替换原来的字段
				sourceAsMap.put("author", new_name);
			}
			if (typeName != null) {
				Text[] fragments = typeName.fragments();
				String new_name = "";
				for (Text text : fragments) {
					new_name += text;
				}
				// 将高亮字段替换原来的字段
				sourceAsMap.put("typeName", new_name);
			}
			list.add(sourceAsMap);
		}

		return list;
	}
}
